package com.hectopascal.auth.component;

import cn.hutool.core.text.AntPathMatcher;
import cn.hutool.core.util.StrUtil;
import com.hectopascal.auth.bean.AdminUserDetails;
import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
    private static final AntPathMatcher ANT = new AntPathMatcher();
    @Resource
    private UserDetailsService userDetailsService;
    @Resource
    private JwtTokenUtil jwtTokenUtil;
    @Resource
    private JwtConfig jwtConfig;
    @Value("${security.permit-url:/backend.org.ums.user.login}")
    private String[] permitUrls;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {

        // 1️⃣ 白名单放行（如登录接口、公共接口）
        if (isPermitted(request)) {
            chain.doFilter(request, response);
            return;
        }

        // 2️⃣ 从请求头读取 JWT
        String tokenHeader = jwtConfig.getTokenHeader(); // 例如 Authorization
        String tokenPrefix = jwtConfig.getTokenHead();   // 例如 Bearer
        String authHeader = request.getHeader(tokenHeader);

        // 3️⃣ JWT 缺失或格式错误 → 直接返回 401
        if (StrUtil.isBlank(authHeader) || !authHeader.startsWith(tokenPrefix)) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.getWriter().write("Unauthorized: JWT missing or invalid");
            return;
        }

        String token = authHeader.substring(tokenPrefix.length()).trim();
        String username = jwtTokenUtil.getUserNameFromToken(token);

        // 4️⃣ 用户名为空或 SecurityContext 已经认证 → 返回 401
        if (StrUtil.isBlank(username) || SecurityContextHolder.getContext().getAuthentication() != null) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.getWriter().write("Unauthorized: JWT invalid");
            return;
        }

        try {
            // 5️⃣ 构造简化的 UserDetails（只保留用户名和 ROLE_USER）
            UserDetails userDetails = userDetailsService.loadUserByUsername(username);

            // 确保加载的是 AdminUserDetails 类型
            if (!(userDetails instanceof AdminUserDetails)) {
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                response.getWriter().write("Unauthorized: User is not an admin");
                return;
            }
            // 6️⃣ 验证 token
            if (!jwtTokenUtil.validateToken(token, userDetails)) {
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                response.getWriter().write("Unauthorized: JWT invalid or expired");
                return;
            }

            // 7️⃣ 设置认证信息到 SecurityContext
            UsernamePasswordAuthenticationToken authentication =
                    new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
            SecurityContextHolder.getContextHolderStrategy().getContext().setAuthentication(authentication);

            log.trace("authenticated user: {}", username);

        } catch (Exception e) {
            log.error("JWT authentication error", e);
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.getWriter().write("Unauthorized: JWT validation error");
            return;
        }

        // 8️⃣ 放行请求
        chain.doFilter(request, response);
    }


    private boolean isPermitted(HttpServletRequest request) {
        // 允许 CORS 预检
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) return true;

        String uri = request.getRequestURI(); // 例如 /login
        if (permitUrls == null) return false;

        for (String raw : permitUrls) {
            if (StrUtil.isBlank(raw)) continue;
            String pattern = raw.trim();
            if (!pattern.startsWith("/")) pattern = "/" + pattern;
            if (ANT.match(pattern, uri)) return true;
        }
        return false;
    }

    private void saveHeaders() {
        Map<String, String> headers = new HashMap<>();
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        Enumeration headerNames = request.getHeaderNames();
        while(headerNames.hasMoreElements()){
            String key = (String) headerNames.nextElement();
            String value = request.getHeader(key);
            headers.put(key, value);
        }
//        FeignConfig.requestHeads.remove();
//        FeignConfig.requestHeads.set(headers);
    }
}
